GailLabel -> GtkLabelAccessible
authorMatthias Clasen <mclasen@redhat.com>
Thu, 23 Jun 2011 05:12:29 +0000 (01:12 -0400)
committerMatthias Clasen <mclasen@redhat.com>
Tue, 5 Jul 2011 20:08:06 +0000 (16:08 -0400)
A first experimental conversion from the gail namespace to gtkaccessible.
At the same time, use gtk_widget_class_set_accessible_type() to register
the accessible type for GtkLabel.

gtk/a11y/Makefile.am
gtk/a11y/gail.c
gtk/a11y/gaillabel.c [deleted file]
gtk/a11y/gaillabel.h [deleted file]
gtk/a11y/gtklabelaccessible.c [new file with mode: 0644]
gtk/a11y/gtklabelaccessible.h [new file with mode: 0644]
gtk/gtklabel.c

index 338b060a6d72825c409f9f756ebe6a6e3857108c..4e914626dccef167d082a8be45d173d86a6a5647 100644 (file)
@@ -23,7 +23,7 @@ gail_c_sources =                      \
        gailframe.c                     \
        gailimage.c                     \
        gailimagecell.c                 \
-       gaillabel.c                     \
+       gtklabelaccessible.c            \
        gaillinkbutton.c                \
        gailmisc.c                      \
        gailmenu.c                      \
@@ -78,7 +78,7 @@ gail_private_h_sources =              \
        gailframe.h                     \
        gailimage.h                     \
        gailimagecell.h                 \
-       gaillabel.h                     \
+       gtklabelaccessible.h            \
        gaillinkbutton.h                \
        gailmisc.h                      \
        gailmenu.h                      \
index 2a8460f53b83c6b01b071b6863c6d51c541a0846..2d369b1a3c0450bae87ee9e1ba2c3ad1a7c30fa8 100644 (file)
@@ -39,7 +39,6 @@
 #include "gailframe.h"
 #include "gailimage.h"
 #include "gailimagecell.h"
-#include "gaillabel.h"
 #include "gaillinkbutton.h"
 #include "gailmenu.h"
 #include "gailmenushell.h"
@@ -129,7 +128,6 @@ GAIL_IMPLEMENT_FACTORY (GAIL_TYPE_WINDOW, GailWindow, gail_window, GTK_TYPE_BIN)
 GAIL_IMPLEMENT_FACTORY (GAIL_TYPE_RANGE, GailRange, gail_range, GTK_TYPE_RANGE)
 GAIL_IMPLEMENT_FACTORY (GAIL_TYPE_SCALE, GailScale, gail_scale, GTK_TYPE_SCALE)
 GAIL_IMPLEMENT_FACTORY (GAIL_TYPE_SCALE_BUTTON, GailScaleButton, gail_scale_button, GTK_TYPE_SCALE_BUTTON)
-GAIL_IMPLEMENT_FACTORY (GAIL_TYPE_LABEL, GailLabel, gail_label, GTK_TYPE_LABEL)
 GAIL_IMPLEMENT_FACTORY (GAIL_TYPE_STATUSBAR, GailStatusbar, gail_statusbar, GTK_TYPE_STATUSBAR)
 GAIL_IMPLEMENT_FACTORY (GAIL_TYPE_NOTEBOOK, GailNotebook, gail_notebook, GTK_TYPE_NOTEBOOK)
 GAIL_IMPLEMENT_FACTORY (GAIL_TYPE_CALENDAR, GailCalendar, gail_calendar, GTK_TYPE_CALENDAR)
@@ -907,7 +905,6 @@ gail_accessibility_module_init (void)
   GAIL_WIDGET_SET_FACTORY (GTK_TYPE_RANGE, gail_range);
   GAIL_WIDGET_SET_FACTORY (GTK_TYPE_SCALE, gail_scale);
   GAIL_WIDGET_SET_FACTORY (GTK_TYPE_SCALE_BUTTON, gail_scale_button);
-  GAIL_WIDGET_SET_FACTORY (GTK_TYPE_LABEL, gail_label);
   GAIL_WIDGET_SET_FACTORY (GTK_TYPE_STATUSBAR, gail_statusbar);
   GAIL_WIDGET_SET_FACTORY (GTK_TYPE_NOTEBOOK, gail_notebook);
   GAIL_WIDGET_SET_FACTORY (GTK_TYPE_CALENDAR, gail_calendar);
diff --git a/gtk/a11y/gaillabel.c b/gtk/a11y/gaillabel.c
deleted file mode 100644 (file)
index e257b73..0000000
+++ /dev/null
@@ -1,1005 +0,0 @@
-/* GAIL - The GNOME Accessibility Enabling Library
- * Copyright 2001, 2002, 2003 Sun Microsystems Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#include "config.h"
-
-#include <string.h>
-
-#include <gtk/gtk.h>
-#include "gaillabel.h"
-#include "gailwindow.h"
-#include <libgail-util/gailmisc.h>
-
-static void       gail_label_class_init            (GailLabelClass    *klass);
-static void       gail_label_init                  (GailLabel         *label);
-static void      gail_label_real_initialize       (AtkObject         *obj,
-                                                    gpointer         data);
-static void      gail_label_real_notify_gtk       (GObject           *obj,
-                                                    GParamSpec       *pspec);
-static void       gail_label_map_gtk               (GtkWidget         *widget,
-                                                    gpointer          data);
-static void       gail_label_init_text_util        (GailLabel         *gail_label,
-                                                    GtkWidget         *widget);
-static void       gail_label_finalize              (GObject           *object);
-
-static void       atk_text_interface_init          (AtkTextIface      *iface);
-
-/* atkobject.h */
-
-static const gchar* gail_label_get_name         (AtkObject         *accessible);
-static AtkStateSet*          gail_label_ref_state_set   (AtkObject         *accessible);
-static AtkRelationSet*       gail_label_ref_relation_set (AtkObject         *accessible);
-
-/* atktext.h */
-
-static gchar*    gail_label_get_text              (AtkText           *text,
-                                                    gint             start_pos,
-                                                   gint              end_pos);
-static gunichar          gail_label_get_character_at_offset(AtkText          *text,
-                                                   gint              offset);
-static gchar*     gail_label_get_text_before_offset(AtkText          *text,
-                                                   gint              offset,
-                                                   AtkTextBoundary   boundary_type,
-                                                   gint              *start_offset,
-                                                   gint              *end_offset);
-static gchar*     gail_label_get_text_at_offset    (AtkText          *text,
-                                                   gint              offset,
-                                                   AtkTextBoundary   boundary_type,
-                                                   gint              *start_offset,
-                                                   gint              *end_offset);
-static gchar*     gail_label_get_text_after_offset    (AtkText       *text,
-                                                   gint              offset,
-                                                   AtkTextBoundary   boundary_type,
-                                                   gint              *start_offset,
-                                                   gint              *end_offset);
-static gint      gail_label_get_character_count   (AtkText           *text);
-static gint      gail_label_get_caret_offset      (AtkText           *text);
-static gboolean          gail_label_set_caret_offset      (AtkText           *text,
-                                                    gint             offset);
-static gint      gail_label_get_n_selections      (AtkText           *text);
-static gchar*    gail_label_get_selection         (AtkText           *text,
-                                                    gint             selection_num,
-                                                    gint             *start_offset,
-                                                    gint             *end_offset);
-static gboolean          gail_label_add_selection         (AtkText           *text,
-                                                    gint             start_offset,
-                                                    gint             end_offset);
-static gboolean          gail_label_remove_selection      (AtkText           *text,
-                                                    gint             selection_num);
-static gboolean          gail_label_set_selection         (AtkText           *text,
-                                                    gint             selection_num,
-                                                    gint             start_offset,
-                                                   gint              end_offset);
-static void gail_label_get_character_extents       (AtkText          *text,
-                                                   gint              offset,
-                                                   gint              *x,
-                                                   gint              *y,
-                                                   gint              *width,
-                                                   gint              *height,
-                                                   AtkCoordType      coords);
-static gint gail_label_get_offset_at_point         (AtkText           *text,
-                                                    gint              x,
-                                                    gint              y,
-                                                   AtkCoordType      coords);
-static AtkAttributeSet* gail_label_get_run_attributes 
-                                                   (AtkText           *text,
-                                                   gint              offset,
-                                                    gint             *start_offset,
-                                                   gint              *end_offset);
-static AtkAttributeSet* gail_label_get_default_attributes
-                                                   (AtkText           *text);
-
-G_DEFINE_TYPE_WITH_CODE (GailLabel, gail_label, GAIL_TYPE_WIDGET,
-                         G_IMPLEMENT_INTERFACE (ATK_TYPE_TEXT, atk_text_interface_init))
-
-static void
-gail_label_class_init (GailLabelClass *klass)
-{
-  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
-  AtkObjectClass  *class = ATK_OBJECT_CLASS (klass);
-  GailWidgetClass *widget_class;
-
-  gobject_class->finalize = gail_label_finalize;
-
-  widget_class = (GailWidgetClass*)klass;
-  widget_class->notify_gtk = gail_label_real_notify_gtk;
-
-  class->get_name = gail_label_get_name;
-  class->ref_state_set = gail_label_ref_state_set;
-  class->ref_relation_set = gail_label_ref_relation_set;
-  class->initialize = gail_label_real_initialize;
-}
-
-static void
-gail_label_init (GailLabel *label)
-{
-}
-
-static void
-gail_label_real_initialize (AtkObject *obj,
-                            gpointer  data)
-{
-  GtkWidget  *widget;
-  GailLabel *gail_label;
-
-  ATK_OBJECT_CLASS (gail_label_parent_class)->initialize (obj, data);
-  
-  gail_label = GAIL_LABEL (obj);
-
-  gail_label->window_create_handler = 0;
-  gail_label->has_top_level = FALSE;
-  gail_label->cursor_position = 0;
-  gail_label->selection_bound = 0;
-  gail_label->textutil = NULL;
-  gail_label->label_length = 0;
-  
-  widget = GTK_WIDGET (data);
-
-  if (gtk_widget_get_mapped (widget))
-    gail_label_init_text_util (gail_label, widget);
-  else
-    g_signal_connect (widget,
-                      "map",
-                      G_CALLBACK (gail_label_map_gtk),
-                      gail_label);
-
-  /* 
-   * Check whether ancestor of GtkLabel is a GtkButton and if so
-   * set accessible parent for GailLabel
-   */
-  while (widget != NULL)
-    {
-      widget = gtk_widget_get_parent (widget);
-      if (GTK_IS_BUTTON (widget))
-        {
-          atk_object_set_parent (obj, gtk_widget_get_accessible (widget));
-          break;
-        }
-    }
-
-  if (GTK_IS_ACCEL_LABEL (widget))
-    obj->role = ATK_ROLE_ACCEL_LABEL;
-  else
-    obj->role = ATK_ROLE_LABEL;
-}
-
-static void
-gail_label_map_gtk (GtkWidget *widget,
-                    gpointer data)
-{
-  GailLabel *gail_label;
-
-  gail_label = GAIL_LABEL (data);
-  gail_label_init_text_util (gail_label, widget);
-}
-
-static void
-gail_label_init_text_util (GailLabel *gail_label,
-                           GtkWidget *widget)
-{
-  GtkLabel *label;
-  const gchar *label_text;
-
-  if (gail_label->textutil == NULL)
-    gail_label->textutil = gail_text_util_new ();
-
-  label = GTK_LABEL (widget);
-  label_text = gtk_label_get_text (label);
-  gail_text_util_text_setup (gail_label->textutil, label_text);
-  
-  if (label_text == NULL)
-    gail_label->label_length = 0;
-  else
-    gail_label->label_length = g_utf8_strlen (label_text, -1);
-}
-
-static void
-notify_name_change (AtkObject *atk_obj)
-{
-  GtkLabel *label;
-  GailLabel *gail_label;
-  GtkWidget *widget;
-  GObject *gail_obj;
-
-  widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (atk_obj));
-  if (widget == NULL)
-    /*
-     * State is defunct
-     */
-    return;
-
-  gail_obj = G_OBJECT (atk_obj);
-  label = GTK_LABEL (widget);
-  gail_label = GAIL_LABEL (atk_obj);
-
-  if (gail_label->textutil == NULL)
-    return;
-
-  /*
-   * Check whether the label has actually changed before emitting
-   * notification.
-   */
-  if (gail_label->textutil->buffer) 
-    {
-      GtkTextIter start, end;
-      const char *new_label;
-      char *old_label;
-      int same;   
-
-      gtk_text_buffer_get_start_iter (gail_label->textutil->buffer, &start);
-      gtk_text_buffer_get_end_iter (gail_label->textutil->buffer, &end);
-      old_label = gtk_text_buffer_get_text (gail_label->textutil->buffer, &start, &end, FALSE);
-      new_label = gtk_label_get_text (label);
-      same = strcmp (new_label, old_label);
-      g_free (old_label);
-      if (same == 0)
-        return;
-    }
-   
-  /* Create a delete text and an insert text signal */
-  g_signal_emit_by_name (gail_obj, "text_changed::delete", 0, 
-                         gail_label->label_length);
-
-  gail_label_init_text_util (gail_label, widget);
-
-  g_signal_emit_by_name (gail_obj, "text_changed::insert", 0, 
-                         gail_label->label_length);
-
-  if (atk_obj->name == NULL)
-    /*
-     * The label has changed so notify a change in accessible-name
-     */
-    g_object_notify (gail_obj, "accessible-name");
-
-  g_signal_emit_by_name (gail_obj, "visible_data_changed");
-}
-
-static void
-window_created (GObject *obj,
-                gpointer data)
-{
-  g_return_if_fail (GAIL_LABEL (data));
-
-  notify_name_change (ATK_OBJECT (data)); 
-}
-
-static void
-gail_label_real_notify_gtk (GObject           *obj,
-                            GParamSpec        *pspec)
-{
-  GtkWidget *widget = GTK_WIDGET (obj);
-  AtkObject* atk_obj = gtk_widget_get_accessible (widget);
-  GtkLabel *label;
-  GailLabel *gail_label;
-  GObject *gail_obj;
-  AtkObject *top_level;
-  AtkObject *temp_obj;
-
-  gail_label = GAIL_LABEL (atk_obj);
-
-  if (strcmp (pspec->name, "label") == 0)
-    {
-     /* 
-      * We may get a label change for a label which is not attached to an
-      * application. We wait until the toplevel window is created before
-      * emitting the notification.
-      *
-      * This happens when [Ctrl+]Alt+Tab is pressed in metacity
-      */
-      if (!gail_label->has_top_level)
-        {
-          temp_obj = atk_obj;
-          top_level = NULL;
-          while (temp_obj)
-            {
-              top_level = temp_obj;
-              temp_obj = atk_object_get_parent (top_level);
-            }
-          if (atk_object_get_role (top_level) != ATK_ROLE_APPLICATION)
-            {
-              if (gail_label->window_create_handler == 0 && 
-                  GAIL_IS_WINDOW (top_level))
-                gail_label->window_create_handler = g_signal_connect_after (top_level, "create", G_CALLBACK (window_created), atk_obj);
-            }
-          else
-            gail_label->has_top_level = TRUE;
-        }
-      if (gail_label->has_top_level)
-        notify_name_change (atk_obj);
-    }
-  else if (strcmp (pspec->name, "cursor-position") == 0)
-    {
-      gint start, end, tmp;
-      gboolean text_caret_moved = FALSE;
-      gboolean selection_changed = FALSE;
-
-      gail_obj = G_OBJECT (atk_obj);
-      label = GTK_LABEL (widget);
-
-      if (gail_label->selection_bound != -1 && gail_label->selection_bound < gail_label->cursor_position)
-        {
-          tmp = gail_label->selection_bound;
-          gail_label->selection_bound = gail_label->cursor_position;
-          gail_label->cursor_position = tmp;
-        }
-
-      if (gtk_label_get_selection_bounds (label, &start, &end))
-        {
-          if (start != gail_label->cursor_position ||
-              end != gail_label->selection_bound)
-            {
-              if (end != gail_label->selection_bound)
-                {
-                  gail_label->selection_bound = start;
-                  gail_label->cursor_position = end;
-                }
-              else
-                {
-                  gail_label->selection_bound = end;
-                  gail_label->cursor_position = start;
-                }
-              text_caret_moved = TRUE;
-              if (start != end)
-                selection_changed = TRUE;
-            }
-        }
-      else 
-        {
-          if (gail_label->cursor_position != gail_label->selection_bound)
-            selection_changed = TRUE;
-          if (gtk_label_get_selectable (label))
-            {
-              if (gail_label->cursor_position != -1 && start != gail_label->cursor_position)
-                text_caret_moved = TRUE;
-              if (gail_label->selection_bound != -1 && end != gail_label->selection_bound)
-                {
-                  text_caret_moved = TRUE;
-                  gail_label->cursor_position = end;
-                  gail_label->selection_bound = start;
-                }
-              else
-                {
-                  gail_label->cursor_position = start;
-                  gail_label->selection_bound = end;
-                }
-            }
-          else
-            {
-              /* GtkLabel has become non selectable */
-
-              gail_label->cursor_position = 0;
-              gail_label->selection_bound = 0;
-              text_caret_moved = TRUE;
-            }
-
-        }
-        if (text_caret_moved)
-          g_signal_emit_by_name (gail_obj, "text_caret_moved", 
-                                 gail_label->cursor_position);
-        if (selection_changed)
-          g_signal_emit_by_name (gail_obj, "text_selection_changed");
-
-    }
-  else
-    GAIL_WIDGET_CLASS (gail_label_parent_class)->notify_gtk (obj, pspec);
-}
-
-static void
-gail_label_finalize (GObject            *object)
-{
-  GailLabel *label = GAIL_LABEL (object);
-
-  if (label->textutil)
-    g_object_unref (label->textutil);
-  G_OBJECT_CLASS (gail_label_parent_class)->finalize (object);
-}
-
-
-/* atkobject.h */
-
-static AtkStateSet*
-gail_label_ref_state_set (AtkObject *accessible)
-{
-  AtkStateSet *state_set;
-  GtkWidget *widget;
-
-  state_set = ATK_OBJECT_CLASS (gail_label_parent_class)->ref_state_set (accessible);
-  widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (accessible));
-
-  if (widget == NULL)
-    return state_set;
-
-  atk_state_set_add_state (state_set, ATK_STATE_MULTI_LINE);
-
-  return state_set;
-}
-
-AtkRelationSet*
-gail_label_ref_relation_set (AtkObject *obj)
-{
-  GtkWidget *widget;
-  AtkRelationSet *relation_set;
-
-  g_return_val_if_fail (GAIL_IS_LABEL (obj), NULL);
-
-  widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (obj));
-  if (widget == NULL)
-    /*
-     * State is defunct
-     */
-    return NULL;
-
-  relation_set = ATK_OBJECT_CLASS (gail_label_parent_class)->ref_relation_set (obj);
-
-  if (!atk_relation_set_contains (relation_set, ATK_RELATION_LABEL_FOR))
-    {
-      /*
-       * Get the mnemonic widget
-       *
-       * The relation set is not updated if the mnemonic widget is changed
-       */
-      GtkWidget *mnemonic_widget = gtk_label_get_mnemonic_widget (GTK_LABEL (widget));
-
-      if (mnemonic_widget)
-        {
-          AtkObject *accessible_array[1];
-          AtkRelation* relation;
-
-          if (!gtk_widget_get_can_focus (mnemonic_widget))
-            {
-            /*
-             * Handle the case where a GtkFileChooserButton is specified as the 
-             * mnemonic widget. use the combobox which is a child of the
-             * GtkFileChooserButton as the mnemonic widget. See bug #359843.
-             */
-             if (GTK_IS_BOX (mnemonic_widget))
-               {
-                  GList *list, *tmpl;
-
-                  list = gtk_container_get_children (GTK_CONTAINER (mnemonic_widget));
-                  if (g_list_length (list) == 2)
-                    {
-                      tmpl = g_list_last (list);
-                      if (GTK_IS_COMBO_BOX(tmpl->data))
-                        {
-                          mnemonic_widget = GTK_WIDGET(tmpl->data);
-                        }
-                    }
-                  g_list_free (list);
-                }
-            }
-          accessible_array[0] = gtk_widget_get_accessible (mnemonic_widget);
-          relation = atk_relation_new (accessible_array, 1,
-                                       ATK_RELATION_LABEL_FOR);
-          atk_relation_set_add (relation_set, relation);
-          /*
-           * Unref the relation so that it is not leaked.
-           */
-          g_object_unref (relation);
-        }
-    }
-  return relation_set;
-}
-
-static const gchar*
-gail_label_get_name (AtkObject *accessible)
-{
-  const gchar *name;
-
-  g_return_val_if_fail (GAIL_IS_LABEL (accessible), NULL);
-
-  name = ATK_OBJECT_CLASS (gail_label_parent_class)->get_name (accessible);
-  if (name != NULL)
-    return name;
-  else
-    {
-      /*
-       * Get the text on the label
-       */
-      GtkWidget *widget;
-
-      widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (accessible));
-      if (widget == NULL)
-        /*
-         * State is defunct
-         */
-        return NULL;
-
-      g_return_val_if_fail (GTK_IS_LABEL (widget), NULL);
-
-      return gtk_label_get_text (GTK_LABEL (widget));
-    }
-}
-
-/* atktext.h */
-
-static void
-atk_text_interface_init (AtkTextIface *iface)
-{
-  iface->get_text = gail_label_get_text;
-  iface->get_character_at_offset = gail_label_get_character_at_offset;
-  iface->get_text_before_offset = gail_label_get_text_before_offset;
-  iface->get_text_at_offset = gail_label_get_text_at_offset;
-  iface->get_text_after_offset = gail_label_get_text_after_offset;
-  iface->get_character_count = gail_label_get_character_count;
-  iface->get_caret_offset = gail_label_get_caret_offset;
-  iface->set_caret_offset = gail_label_set_caret_offset;
-  iface->get_n_selections = gail_label_get_n_selections;
-  iface->get_selection = gail_label_get_selection;
-  iface->add_selection = gail_label_add_selection;
-  iface->remove_selection = gail_label_remove_selection;
-  iface->set_selection = gail_label_set_selection;
-  iface->get_character_extents = gail_label_get_character_extents;
-  iface->get_offset_at_point = gail_label_get_offset_at_point;
-  iface->get_run_attributes = gail_label_get_run_attributes;
-  iface->get_default_attributes = gail_label_get_default_attributes;
-}
-
-static gchar*
-gail_label_get_text (AtkText *text,
-                     gint    start_pos,
-                     gint    end_pos)
-{
-  GtkWidget *widget;
-  GtkLabel  *label;
-
-  const gchar *label_text;
-
-  widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
-  if (widget == NULL)
-    /* State is defunct */
-    return NULL;
-
-  label = GTK_LABEL (widget);
-
-  label_text = gtk_label_get_text (label);
-  if (label_text == NULL)
-    return NULL;
-  else
-  {
-    if (GAIL_LABEL (text)->textutil == NULL) 
-      gail_label_init_text_util (GAIL_LABEL (text), widget);
-    return gail_text_util_get_substring (GAIL_LABEL(text)->textutil, 
-                                         start_pos, end_pos);
-  }
-}
-
-static gchar*
-gail_label_get_text_before_offset (AtkText         *text,
-                                  gint            offset,
-                                  AtkTextBoundary boundary_type,
-                                  gint            *start_offset,
-                                  gint            *end_offset)
-{
-  GtkWidget *widget;
-  GtkLabel *label;
-  
-  widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
-  
-  if (widget == NULL)
-    /* State is defunct */
-    return NULL;
-  
-  /* Get label */
-  label = GTK_LABEL (widget);
-
-  return gail_text_util_get_text (GAIL_LABEL (text)->textutil,
-                           gtk_label_get_layout (label), GAIL_BEFORE_OFFSET, 
-                           boundary_type, offset, start_offset, end_offset); 
-}
-
-static gchar*
-gail_label_get_text_at_offset (AtkText         *text,
-                              gint            offset,
-                              AtkTextBoundary boundary_type,
-                              gint            *start_offset,
-                              gint            *end_offset)
-{
-  GtkWidget *widget;
-  GtkLabel *label;
-  widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
-  
-  if (widget == NULL)
-    /* State is defunct */
-    return NULL;
-  
-  /* Get label */
-  label = GTK_LABEL (widget);
-
-  return gail_text_util_get_text (GAIL_LABEL (text)->textutil,
-                              gtk_label_get_layout (label), GAIL_AT_OFFSET, 
-                              boundary_type, offset, start_offset, end_offset);
-}
-
-static gchar*
-gail_label_get_text_after_offset (AtkText         *text,
-                                 gint            offset,
-                                 AtkTextBoundary boundary_type,
-                                 gint            *start_offset,
-                                 gint            *end_offset)
-{
-  GtkWidget *widget;
-  GtkLabel *label;
-
-  widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
-  
-  if (widget == NULL)
-  {
-    /* State is defunct */
-    return NULL;
-  }
-  
-  /* Get label */
-  label = GTK_LABEL (widget);
-
-  return gail_text_util_get_text (GAIL_LABEL (text)->textutil,
-                           gtk_label_get_layout (label), GAIL_AFTER_OFFSET, 
-                           boundary_type, offset, start_offset, end_offset);
-}
-
-static gint
-gail_label_get_character_count (AtkText *text)
-{
-  GtkWidget *widget;
-  GtkLabel  *label;
-
-  widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
-  if (widget == NULL)
-    /* State is defunct */
-    return 0;
-
-  label = GTK_LABEL (widget);
-  return g_utf8_strlen (gtk_label_get_text (label), -1);
-}
-
-static gint
-gail_label_get_caret_offset (AtkText *text)
-{
-   return GAIL_LABEL (text)->cursor_position;
-}
-
-static gboolean
-gail_label_set_caret_offset (AtkText *text, 
-                             gint    offset)
-{
-  GtkWidget *widget;
-  GtkLabel  *label;
-
-  widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
-  if (widget == NULL)
-    /* State is defunct */
-    return 0;
-
-  label = GTK_LABEL (widget);
-
-  if (gtk_label_get_selectable (label) &&
-      offset >= 0 &&
-      offset <= g_utf8_strlen (gtk_label_get_text (label), -1))
-    {
-      gtk_label_select_region (label, offset, offset);
-      return TRUE;
-    }
-  else
-    return FALSE;
-}
-
-static gint
-gail_label_get_n_selections (AtkText *text)
-{
-  GtkWidget *widget;
-  GtkLabel  *label;
-  gint start, end;
-
-  widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
-  if (widget == NULL)
-    /* State is defunct */
-    return 0;
-
-  label = GTK_LABEL (widget);
-
-  if (!gtk_label_get_selectable (label))
-     return 0;
-
-  if (gtk_label_get_selection_bounds (label, &start, &end))
-     return 1;
-  else 
-     return 0;
-}
-
-static gchar*
-gail_label_get_selection (AtkText *text,
-                         gint    selection_num,
-                          gint    *start_pos,
-                          gint    *end_pos)
-{
-  GtkWidget *widget;
-  GtkLabel  *label;
-
-  widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
-  if (widget == NULL)
-    /* State is defunct */
-    return NULL;
-
-  label = GTK_LABEL (widget);
-
- /* Only let the user get the selection if one is set, and if the
-  * selection_num is 0.
-  */
-  if (!gtk_label_get_selectable( label) || selection_num != 0)
-     return NULL;
-
-  if (gtk_label_get_selection_bounds (label, start_pos, end_pos))
-    {
-      const gchar* label_text = gtk_label_get_text (label);
-    
-      if (label_text == NULL)
-        return 0;
-      else
-        return gail_text_util_get_substring (GAIL_LABEL (text)->textutil, 
-                                             *start_pos, *end_pos);
-    }
-  else 
-    return NULL;
-}
-
-static gboolean
-gail_label_add_selection (AtkText *text,
-                          gint    start_pos,
-                          gint    end_pos)
-{
-  GtkWidget *widget;
-  GtkLabel  *label;
-  gint start, end;
-
-  widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
-  if (widget == NULL)
-    /* State is defunct */
-    return FALSE;
-
-  label = GTK_LABEL (widget);
-
-  if (!gtk_label_get_selectable (label))
-     return FALSE;
-
-  if (! gtk_label_get_selection_bounds (label, &start, &end))
-    {
-      gtk_label_select_region (label, start_pos, end_pos);
-      return TRUE;
-    }
-  else
-    return FALSE;
-}
-
-static gboolean
-gail_label_remove_selection (AtkText *text,
-                             gint    selection_num)
-{
-  GtkWidget *widget;
-  GtkLabel  *label;
-  gint start, end;
-
-  widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
-  if (widget == NULL)
-    /* State is defunct */
-    return FALSE;
-
-  if (selection_num != 0)
-     return FALSE;
-
-  label = GTK_LABEL (widget);
-
-  if (!gtk_label_get_selectable (label))
-     return FALSE;
-
-  if (gtk_label_get_selection_bounds (label, &start, &end))
-    {
-      gtk_label_select_region (label, 0, 0);
-      return TRUE;
-    }
-  else
-    return FALSE;
-}
-
-static gboolean
-gail_label_set_selection (AtkText *text,
-                         gint    selection_num,
-                          gint    start_pos,
-                          gint    end_pos)
-{
-  GtkWidget *widget;
-  GtkLabel  *label;
-  gint start, end;
-
-  widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
-  if (widget == NULL)
-    /* State is defunct */
-    return FALSE;
-
-  if (selection_num != 0)
-     return FALSE;
-
-  label = GTK_LABEL (widget);
-
-  if (!gtk_label_get_selectable (label))
-     return FALSE;
-
-  if (gtk_label_get_selection_bounds (label, &start, &end))
-    {
-      gtk_label_select_region (label, start_pos, end_pos);
-      return TRUE;
-    }
-  else
-    return FALSE;
-}
-
-static void
-gail_label_get_character_extents (AtkText      *text,
-                                 gint         offset,
-                                 gint         *x,
-                                 gint         *y,
-                                  gint                *width,
-                                  gint                *height,
-                                 AtkCoordType coords)
-{
-  GtkWidget *widget;
-  GtkLabel *label;
-  PangoRectangle char_rect;
-  const gchar *label_text;
-  gint index, x_layout, y_layout;
-  widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
-
-  if (widget == NULL)
-    /* State is defunct */
-    return;
-
-  label = GTK_LABEL (widget);
-  
-  gtk_label_get_layout_offsets (label, &x_layout, &y_layout);
-  label_text = gtk_label_get_text (label);
-  index = g_utf8_offset_to_pointer (label_text, offset) - label_text;
-  pango_layout_index_to_pos (gtk_label_get_layout (label), index, &char_rect);
-  
-  gail_misc_get_extents_from_pango_rectangle (widget, &char_rect, 
-                    x_layout, y_layout, x, y, width, height, coords);
-} 
-
-static gint 
-gail_label_get_offset_at_point (AtkText      *text,
-                                gint         x,
-                                gint         y,
-                               AtkCoordType coords)
-{ 
-  GtkWidget *widget;
-  GtkLabel *label;
-  const gchar *label_text;
-  gint index, x_layout, y_layout;
-
-  widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
-  if (widget == NULL)
-    /* State is defunct */
-    return -1;
-  label = GTK_LABEL (widget);
-  
-  gtk_label_get_layout_offsets (label, &x_layout, &y_layout);
-  
-  index = gail_misc_get_index_at_point_in_layout (widget, 
-                                              gtk_label_get_layout (label), 
-                                              x_layout, y_layout, x, y, coords);
-  label_text = gtk_label_get_text (label);
-  if (index == -1)
-    {
-      if (coords == ATK_XY_WINDOW || coords == ATK_XY_SCREEN)
-        return g_utf8_strlen (label_text, -1);
-
-      return index;  
-    }
-  else
-    return g_utf8_pointer_to_offset (label_text, label_text + index);
-}
-
-static AtkAttributeSet*
-gail_label_get_run_attributes (AtkText        *text,
-                               gint          offset,
-                               gint          *start_offset,
-                              gint           *end_offset)
-{
-  GtkWidget *widget;
-  GtkLabel *label;
-  AtkAttributeSet *at_set = NULL;
-  GtkJustification justify;
-  GtkTextDirection dir;
-
-  widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
-  if (widget == NULL)
-    /* State is defunct */
-    return NULL;
-
-  label = GTK_LABEL (widget);
-  
-  /* Get values set for entire label, if any */
-  justify = gtk_label_get_justify (label);
-  if (justify != GTK_JUSTIFY_CENTER)
-    {
-      at_set = gail_misc_add_attribute (at_set, 
-                                        ATK_TEXT_ATTR_JUSTIFICATION,
-     g_strdup (atk_text_attribute_get_value (ATK_TEXT_ATTR_JUSTIFICATION, justify)));
-    }
-  dir = gtk_widget_get_direction (widget);
-  if (dir == GTK_TEXT_DIR_RTL)
-    {
-      at_set = gail_misc_add_attribute (at_set, 
-                                        ATK_TEXT_ATTR_DIRECTION,
-     g_strdup (atk_text_attribute_get_value (ATK_TEXT_ATTR_DIRECTION, dir)));
-    }
-
-  at_set = gail_misc_layout_get_run_attributes (at_set,
-                                                gtk_label_get_layout (label),
-                                                gtk_label_get_text (label),
-                                                offset,
-                                                start_offset,
-                                                end_offset);
-  return at_set;
-}
-
-static AtkAttributeSet*
-gail_label_get_default_attributes (AtkText        *text)
-{
-  GtkWidget *widget;
-  GtkLabel *label;
-  AtkAttributeSet *at_set = NULL;
-
-  widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
-  if (widget == NULL)
-    /* State is defunct */
-    return NULL;
-
-  label = GTK_LABEL (widget);
-  
-  at_set = gail_misc_get_default_attributes (at_set,
-                                             gtk_label_get_layout (label),
-                                             widget);
-  return at_set;
-}
-
-static gunichar 
-gail_label_get_character_at_offset (AtkText             *text,
-                                    gint                offset)
-{
-  GtkWidget *widget;
-  GtkLabel *label;
-  const gchar *string;
-  gchar *index;
-
-  widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
-  if (widget == NULL)
-    /* State is defunct */
-    return '\0';
-
-  label = GTK_LABEL (widget);
-  string = gtk_label_get_text (label);
-  if (offset >= g_utf8_strlen (string, -1))
-    return '\0';
-  index = g_utf8_offset_to_pointer (string, offset);
-
-  return g_utf8_get_char (index);
-}
diff --git a/gtk/a11y/gaillabel.h b/gtk/a11y/gaillabel.h
deleted file mode 100644 (file)
index fa4b657..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-/* GAIL - The GNOME Accessibility Implementation Library
- * Copyright 2001 Sun Microsystems Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifndef __GAIL_LABEL_H__
-#define __GAIL_LABEL_H__
-
-#include "gailwidget.h"
-#include "gailtextutil.h"
-
-G_BEGIN_DECLS
-
-#define GAIL_TYPE_LABEL                      (gail_label_get_type ())
-#define GAIL_LABEL(obj)                      (G_TYPE_CHECK_INSTANCE_CAST ((obj), GAIL_TYPE_LABEL, GailLabel))
-#define GAIL_LABEL_CLASS(klass)              (G_TYPE_CHECK_CLASS_CAST ((klass), GAIL_TYPE_LABEL, GailLabelClass))
-#define GAIL_IS_LABEL(obj)                   (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GAIL_TYPE_LABEL))
-#define GAIL_IS_LABEL_CLASS(klass)           (G_TYPE_CHECK_CLASS_TYPE ((klass), GAIL_TYPE_LABEL))
-#define GAIL_LABEL_GET_CLASS(obj)            (G_TYPE_INSTANCE_GET_CLASS ((obj), GAIL_TYPE_LABEL, GailLabelClass))
-
-typedef struct _GailLabel              GailLabel;
-typedef struct _GailLabelClass         GailLabelClass;
-
-struct _GailLabel
-{
-  GailWidget parent;
-
-  GailTextUtil   *textutil;
-  gint           cursor_position;
-  gint           selection_bound;
-  gint           label_length;
-  gulong         window_create_handler;
-  gboolean       has_top_level;
-};
-
-GType gail_label_get_type (void);
-
-struct _GailLabelClass
-{
-  GailWidgetClass parent_class;
-};
-
-G_END_DECLS
-
-#endif /* __GAIL_LABEL_H__ */
diff --git a/gtk/a11y/gtklabelaccessible.c b/gtk/a11y/gtklabelaccessible.c
new file mode 100644 (file)
index 0000000..e3ccfd1
--- /dev/null
@@ -0,0 +1,1005 @@
+/* GAIL - The GNOME Accessibility Enabling Library
+ * Copyright 2001, 2002, 2003 Sun Microsystems Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include <string.h>
+
+#include <gtk/gtk.h>
+#include "gtklabelaccessible.h"
+#include "gailwindow.h"
+#include <libgail-util/gailmisc.h>
+
+static void       gtk_label_accessible_class_init            (GtkLabelAccessibleClass    *klass);
+static void       gtk_label_accessible_init                  (GtkLabelAccessible         *label);
+static void      gtk_label_accessible_real_initialize     (AtkObject         *obj,
+                                                    gpointer         data);
+static void      gtk_label_accessible_real_notify_gtk     (GObject           *obj,
+                                                    GParamSpec       *pspec);
+static void       gtk_label_accessible_map_gtk               (GtkWidget         *widget,
+                                                    gpointer          data);
+static void       gtk_label_accessible_init_text_util        (GtkLabelAccessible         *gail_label,
+                                                    GtkWidget         *widget);
+static void       gtk_label_accessible_finalize              (GObject           *object);
+
+static void       atk_text_interface_init          (AtkTextIface      *iface);
+
+/* atkobject.h */
+
+static const gchar* gtk_label_accessible_get_name         (AtkObject         *accessible);
+static AtkStateSet*          gtk_label_accessible_ref_state_set         (AtkObject         *accessible);
+static AtkRelationSet*       gtk_label_accessible_ref_relation_set (AtkObject         *accessible);
+
+/* atktext.h */
+
+static gchar*    gtk_label_accessible_get_text            (AtkText           *text,
+                                                    gint             start_pos,
+                                                   gint              end_pos);
+static gunichar          gtk_label_accessible_get_character_at_offset(AtkText        *text,
+                                                   gint              offset);
+static gchar*     gtk_label_accessible_get_text_before_offset(AtkText        *text,
+                                                   gint              offset,
+                                                   AtkTextBoundary   boundary_type,
+                                                   gint              *start_offset,
+                                                   gint              *end_offset);
+static gchar*     gtk_label_accessible_get_text_at_offset    (AtkText        *text,
+                                                   gint              offset,
+                                                   AtkTextBoundary   boundary_type,
+                                                   gint              *start_offset,
+                                                   gint              *end_offset);
+static gchar*     gtk_label_accessible_get_text_after_offset    (AtkText             *text,
+                                                   gint              offset,
+                                                   AtkTextBoundary   boundary_type,
+                                                   gint              *start_offset,
+                                                   gint              *end_offset);
+static gint      gtk_label_accessible_get_character_count   (AtkText         *text);
+static gint      gtk_label_accessible_get_caret_offset    (AtkText           *text);
+static gboolean          gtk_label_accessible_set_caret_offset    (AtkText           *text,
+                                                    gint             offset);
+static gint      gtk_label_accessible_get_n_selections    (AtkText           *text);
+static gchar*    gtk_label_accessible_get_selection       (AtkText           *text,
+                                                    gint             selection_num,
+                                                    gint             *start_offset,
+                                                    gint             *end_offset);
+static gboolean          gtk_label_accessible_add_selection       (AtkText           *text,
+                                                    gint             start_offset,
+                                                    gint             end_offset);
+static gboolean          gtk_label_accessible_remove_selection    (AtkText           *text,
+                                                    gint             selection_num);
+static gboolean          gtk_label_accessible_set_selection       (AtkText           *text,
+                                                    gint             selection_num,
+                                                    gint             start_offset,
+                                                   gint              end_offset);
+static void gtk_label_accessible_get_character_extents       (AtkText        *text,
+                                                   gint              offset,
+                                                   gint              *x,
+                                                   gint              *y,
+                                                   gint              *width,
+                                                   gint              *height,
+                                                   AtkCoordType      coords);
+static gint gtk_label_accessible_get_offset_at_point         (AtkText           *text,
+                                                    gint              x,
+                                                    gint              y,
+                                                   AtkCoordType      coords);
+static AtkAttributeSet* gtk_label_accessible_get_run_attributes 
+                                                   (AtkText           *text,
+                                                   gint              offset,
+                                                    gint             *start_offset,
+                                                   gint              *end_offset);
+static AtkAttributeSet* gtk_label_accessible_get_default_attributes
+                                                   (AtkText           *text);
+
+G_DEFINE_TYPE_WITH_CODE (GtkLabelAccessible, gtk_label_accessible, GAIL_TYPE_WIDGET,
+                         G_IMPLEMENT_INTERFACE (ATK_TYPE_TEXT, atk_text_interface_init))
+
+static void
+gtk_label_accessible_class_init (GtkLabelAccessibleClass *klass)
+{
+  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+  AtkObjectClass  *class = ATK_OBJECT_CLASS (klass);
+  GailWidgetClass *widget_class;
+
+  gobject_class->finalize = gtk_label_accessible_finalize;
+
+  widget_class = (GailWidgetClass*)klass;
+  widget_class->notify_gtk = gtk_label_accessible_real_notify_gtk;
+
+  class->get_name = gtk_label_accessible_get_name;
+  class->ref_state_set = gtk_label_accessible_ref_state_set;
+  class->ref_relation_set = gtk_label_accessible_ref_relation_set;
+  class->initialize = gtk_label_accessible_real_initialize;
+}
+
+static void
+gtk_label_accessible_init (GtkLabelAccessible *label)
+{
+}
+
+static void
+gtk_label_accessible_real_initialize (AtkObject *obj,
+                            gpointer  data)
+{
+  GtkWidget  *widget;
+  GtkLabelAccessible *accessible;
+
+  ATK_OBJECT_CLASS (gtk_label_accessible_parent_class)->initialize (obj, data);
+  
+  accessible = GTK_LABEL_ACCESSIBLE (obj);
+
+  accessible->window_create_handler = 0;
+  accessible->has_top_level = FALSE;
+  accessible->cursor_position = 0;
+  accessible->selection_bound = 0;
+  accessible->textutil = NULL;
+  accessible->label_length = 0;
+  
+  widget = GTK_WIDGET (data);
+
+  if (gtk_widget_get_mapped (widget))
+    gtk_label_accessible_init_text_util (accessible, widget);
+  else
+    g_signal_connect (widget, "map",
+                      G_CALLBACK (gtk_label_accessible_map_gtk),
+                      accessible);
+
+  /*
+   * Check whether ancestor of GtkLabel is a GtkButton and if so
+   * set accessible parent for GtkLabelAccessible
+   */
+  while (widget != NULL)
+    {
+      widget = gtk_widget_get_parent (widget);
+      if (GTK_IS_BUTTON (widget))
+        {
+          atk_object_set_parent (obj, gtk_widget_get_accessible (widget));
+          break;
+        }
+    }
+
+  if (GTK_IS_ACCEL_LABEL (widget))
+    obj->role = ATK_ROLE_ACCEL_LABEL;
+  else
+    obj->role = ATK_ROLE_LABEL;
+}
+
+static void
+gtk_label_accessible_map_gtk (GtkWidget *widget,
+                    gpointer data)
+{
+  GtkLabelAccessible *accessible;
+
+  accessible = GTK_LABEL_ACCESSIBLE (data);
+  gtk_label_accessible_init_text_util (accessible, widget);
+}
+
+static void
+gtk_label_accessible_init_text_util (GtkLabelAccessible *accessible,
+                           GtkWidget *widget)
+{
+  GtkLabel *label;
+  const gchar *label_text;
+
+  if (accessible->textutil == NULL)
+    accessible->textutil = gail_text_util_new ();
+
+  label = GTK_LABEL (widget);
+  label_text = gtk_label_get_text (label);
+  gail_text_util_text_setup (accessible->textutil, label_text);
+  
+  if (label_text == NULL)
+    accessible->label_length = 0;
+  else
+    accessible->label_length = g_utf8_strlen (label_text, -1);
+}
+
+static void
+notify_name_change (AtkObject *atk_obj)
+{
+  GtkLabel *label;
+  GtkLabelAccessible *accessible;
+  GtkWidget *widget;
+  GObject *gail_obj;
+
+  widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (atk_obj));
+  if (widget == NULL)
+    /*
+     * State is defunct
+     */
+    return;
+
+  gail_obj = G_OBJECT (atk_obj);
+  label = GTK_LABEL (widget);
+  accessible = GTK_LABEL_ACCESSIBLE (atk_obj);
+
+  if (accessible->textutil == NULL)
+    return;
+
+  /*
+   * Check whether the label has actually changed before emitting
+   * notification.
+   */
+  if (accessible->textutil->buffer)
+    {
+      GtkTextIter start, end;
+      const char *new_label;
+      char *old_label;
+      int same;
+
+      gtk_text_buffer_get_start_iter (accessible->textutil->buffer, &start);
+      gtk_text_buffer_get_end_iter (accessible->textutil->buffer, &end);
+      old_label = gtk_text_buffer_get_text (accessible->textutil->buffer, &start, &end, FALSE);
+      new_label = gtk_label_get_text (label);
+      same = strcmp (new_label, old_label);
+      g_free (old_label);
+      if (same == 0)
+        return;
+    }
+
+  /* Create a delete text and an insert text signal */
+
+  g_signal_emit_by_name (gail_obj, "text_changed::delete", 0,
+                         accessible->label_length);
+
+  gtk_label_accessible_init_text_util (accessible, widget);
+
+  g_signal_emit_by_name (gail_obj, "text_changed::insert", 0, 
+                         accessible->label_length);
+
+  if (atk_obj->name == NULL)
+    /*
+     * The label has changed so notify a change in accessible-name
+     */
+    g_object_notify (gail_obj, "accessible-name");
+
+  g_signal_emit_by_name (gail_obj, "visible_data_changed");
+}
+
+static void
+window_created (GObject *obj,
+                gpointer data)
+{
+  g_return_if_fail (GTK_LABEL_ACCESSIBLE (data));
+
+  notify_name_change (ATK_OBJECT (data)); 
+}
+
+static void
+gtk_label_accessible_real_notify_gtk (GObject           *obj,
+                                GParamSpec        *pspec)
+{
+  GtkWidget *widget = GTK_WIDGET (obj);
+  AtkObject* atk_obj = gtk_widget_get_accessible (widget);
+  GtkLabel *label;
+  GtkLabelAccessible *accessible;
+  GObject *gail_obj;
+  AtkObject *top_level;
+  AtkObject *temp_obj;
+
+  accessible = GTK_LABEL_ACCESSIBLE (atk_obj);
+
+  if (strcmp (pspec->name, "label") == 0)
+    {
+     /* 
+      * We may get a label change for a label which is not attached to an
+      * application. We wait until the toplevel window is created before
+      * emitting the notification.
+      *
+      * This happens when [Ctrl+]Alt+Tab is pressed in metacity
+      */
+      if (!accessible->has_top_level)
+        {
+          temp_obj = atk_obj;
+          top_level = NULL;
+          while (temp_obj)
+            {
+              top_level = temp_obj;
+              temp_obj = atk_object_get_parent (top_level);
+            }
+          if (atk_object_get_role (top_level) != ATK_ROLE_APPLICATION)
+            {
+              if (accessible->window_create_handler == 0 && 
+                  GAIL_IS_WINDOW (top_level))
+                accessible->window_create_handler = g_signal_connect_after (top_level, "create", G_CALLBACK (window_created), atk_obj);
+            }
+          else
+            accessible->has_top_level = TRUE;
+        }
+      if (accessible->has_top_level)
+        notify_name_change (atk_obj);
+    }
+  else if (strcmp (pspec->name, "cursor-position") == 0)
+    {
+      gint start, end, tmp;
+      gboolean text_caret_moved = FALSE;
+      gboolean selection_changed = FALSE;
+
+      gail_obj = G_OBJECT (atk_obj);
+      label = GTK_LABEL (widget);
+
+      if (accessible->selection_bound != -1 && accessible->selection_bound < accessible->cursor_position)
+        {
+          tmp = accessible->selection_bound;
+          accessible->selection_bound = accessible->cursor_position;
+          accessible->cursor_position = tmp;
+        }
+
+      if (gtk_label_get_selection_bounds (label, &start, &end))
+        {
+          if (start != accessible->cursor_position ||
+              end != accessible->selection_bound)
+            {
+              if (end != accessible->selection_bound)
+                {
+                  accessible->selection_bound = start;
+                  accessible->cursor_position = end;
+                }
+              else
+                {
+                  accessible->selection_bound = end;
+                  accessible->cursor_position = start;
+                }
+              text_caret_moved = TRUE;
+              if (start != end)
+                selection_changed = TRUE;
+            }
+        }
+      else
+        {
+          if (accessible->cursor_position != accessible->selection_bound)
+            selection_changed = TRUE;
+          if (gtk_label_get_selectable (label))
+            {
+              if (accessible->cursor_position != -1 && start != accessible->cursor_position)
+                text_caret_moved = TRUE;
+              if (accessible->selection_bound != -1 && end != accessible
+->selection_bound)
+                {
+                  text_caret_moved = TRUE;
+                  accessible->cursor_position = end;
+                  accessible->selection_bound = start;
+                }
+              else
+                {
+                  accessible->cursor_position = start;
+                  accessible->selection_bound = end;
+                }
+            }
+          else
+            {
+              /* GtkLabel has become non selectable */
+
+              accessible->cursor_position = 0;
+              accessible->selection_bound = 0;
+              text_caret_moved = TRUE;
+            }
+
+        }
+        if (text_caret_moved)
+          g_signal_emit_by_name (gail_obj, "text_caret_moved",
+                                 accessible->cursor_position);
+        if (selection_changed)
+          g_signal_emit_by_name (gail_obj, "text_selection_changed");
+
+    }
+  else
+    GAIL_WIDGET_CLASS (gtk_label_accessible_parent_class)->notify_gtk (obj, pspec);
+}
+
+static void
+gtk_label_accessible_finalize (GObject *object)
+{
+  GtkLabelAccessible *accessible = GTK_LABEL_ACCESSIBLE (object);
+
+  if (accessible->textutil)
+    g_object_unref (accessible->textutil);
+  G_OBJECT_CLASS (gtk_label_accessible_parent_class)->finalize (object);
+}
+
+
+/* atkobject.h */
+
+static AtkStateSet*
+gtk_label_accessible_ref_state_set (AtkObject *accessible)
+{
+  AtkStateSet *state_set;
+  GtkWidget *widget;
+
+  state_set = ATK_OBJECT_CLASS (gtk_label_accessible_parent_class)->ref_state_set (accessible);
+  widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (accessible));
+
+  if (widget == NULL)
+    return state_set;
+
+  atk_state_set_add_state (state_set, ATK_STATE_MULTI_LINE);
+
+  return state_set;
+}
+
+AtkRelationSet*
+gtk_label_accessible_ref_relation_set (AtkObject *obj)
+{
+  GtkWidget *widget;
+  AtkRelationSet *relation_set;
+
+  g_return_val_if_fail (GTK_IS_LABEL_ACCESSIBLE (obj), NULL);
+
+  widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (obj));
+  if (widget == NULL)
+    /*
+     * State is defunct
+     */
+    return NULL;
+
+  relation_set = ATK_OBJECT_CLASS (gtk_label_accessible_parent_class)->ref_relation_set (obj);
+
+  if (!atk_relation_set_contains (relation_set, ATK_RELATION_LABEL_FOR))
+    {
+      /*
+       * Get the mnemonic widget
+       *
+       * The relation set is not updated if the mnemonic widget is changed
+       */
+      GtkWidget *mnemonic_widget = gtk_label_get_mnemonic_widget (GTK_LABEL (widget));
+
+      if (mnemonic_widget)
+        {
+          AtkObject *accessible_array[1];
+          AtkRelation* relation;
+
+          if (!gtk_widget_get_can_focus (mnemonic_widget))
+            {
+            /*
+             * Handle the case where a GtkFileChooserButton is specified as the 
+             * mnemonic widget. use the combobox which is a child of the
+             * GtkFileChooserButton as the mnemonic widget. See bug #359843.
+             */
+             if (GTK_IS_BOX (mnemonic_widget))
+               {
+                  GList *list, *tmpl;
+
+                  list = gtk_container_get_children (GTK_CONTAINER (mnemonic_widget));
+                  if (g_list_length (list) == 2)
+                    {
+                      tmpl = g_list_last (list);
+                      if (GTK_IS_COMBO_BOX(tmpl->data))
+                        {
+                          mnemonic_widget = GTK_WIDGET(tmpl->data);
+                        }
+                    }
+                  g_list_free (list);
+                }
+            }
+          accessible_array[0] = gtk_widget_get_accessible (mnemonic_widget);
+          relation = atk_relation_new (accessible_array, 1,
+                                       ATK_RELATION_LABEL_FOR);
+          atk_relation_set_add (relation_set, relation);
+          /*
+           * Unref the relation so that it is not leaked.
+           */
+          g_object_unref (relation);
+        }
+    }
+  return relation_set;
+}
+
+static const gchar*
+gtk_label_accessible_get_name (AtkObject *accessible)
+{
+  const gchar *name;
+
+  g_return_val_if_fail (GTK_IS_LABEL_ACCESSIBLE (accessible), NULL);
+
+  name = ATK_OBJECT_CLASS (gtk_label_accessible_parent_class)->get_name (accessible);
+  if (name != NULL)
+    return name;
+  else
+    {
+      /*
+       * Get the text on the label
+       */
+      GtkWidget *widget;
+
+      widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (accessible));
+      if (widget == NULL)
+        /*
+         * State is defunct
+         */
+        return NULL;
+
+      g_return_val_if_fail (GTK_IS_LABEL (widget), NULL);
+
+      return gtk_label_get_text (GTK_LABEL (widget));
+    }
+}
+
+/* atktext.h */
+
+static void
+atk_text_interface_init (AtkTextIface *iface)
+{
+  iface->get_text = gtk_label_accessible_get_text;
+  iface->get_character_at_offset = gtk_label_accessible_get_character_at_offset;
+  iface->get_text_before_offset = gtk_label_accessible_get_text_before_offset;
+  iface->get_text_at_offset = gtk_label_accessible_get_text_at_offset;
+  iface->get_text_after_offset = gtk_label_accessible_get_text_after_offset;
+  iface->get_character_count = gtk_label_accessible_get_character_count;
+  iface->get_caret_offset = gtk_label_accessible_get_caret_offset;
+  iface->set_caret_offset = gtk_label_accessible_set_caret_offset;
+  iface->get_n_selections = gtk_label_accessible_get_n_selections;
+  iface->get_selection = gtk_label_accessible_get_selection;
+  iface->add_selection = gtk_label_accessible_add_selection;
+  iface->remove_selection = gtk_label_accessible_remove_selection;
+  iface->set_selection = gtk_label_accessible_set_selection;
+  iface->get_character_extents = gtk_label_accessible_get_character_extents;
+  iface->get_offset_at_point = gtk_label_accessible_get_offset_at_point;
+  iface->get_run_attributes = gtk_label_accessible_get_run_attributes;
+  iface->get_default_attributes = gtk_label_accessible_get_default_attributes;
+}
+
+static gchar*
+gtk_label_accessible_get_text (AtkText *text,
+                     gint    start_pos,
+                     gint    end_pos)
+{
+  GtkWidget *widget;
+  GtkLabel  *label;
+
+  const gchar *label_text;
+
+  widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
+  if (widget == NULL)
+    /* State is defunct */
+    return NULL;
+
+  label = GTK_LABEL (widget);
+
+  label_text = gtk_label_get_text (label);
+  if (label_text == NULL)
+    return NULL;
+  else
+  {
+    if (GTK_LABEL_ACCESSIBLE (text)->textutil == NULL) 
+      gtk_label_accessible_init_text_util (GTK_LABEL_ACCESSIBLE (text), widget);
+    return gail_text_util_get_substring (GTK_LABEL_ACCESSIBLE (text)->textutil, 
+                                         start_pos, end_pos);
+  }
+}
+
+static gchar*
+gtk_label_accessible_get_text_before_offset (AtkText         *text,
+                                  gint            offset,
+                                  AtkTextBoundary boundary_type,
+                                  gint            *start_offset,
+                                  gint            *end_offset)
+{
+  GtkWidget *widget;
+  GtkLabel *label;
+  
+  widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
+  
+  if (widget == NULL)
+    /* State is defunct */
+    return NULL;
+  
+  /* Get label */
+  label = GTK_LABEL (widget);
+
+  return gail_text_util_get_text (GTK_LABEL_ACCESSIBLE (text)->textutil,
+                           gtk_label_get_layout (label), GAIL_BEFORE_OFFSET, 
+                           boundary_type, offset, start_offset, end_offset); 
+}
+
+static gchar*
+gtk_label_accessible_get_text_at_offset (AtkText         *text,
+                              gint            offset,
+                              AtkTextBoundary boundary_type,
+                              gint            *start_offset,
+                              gint            *end_offset)
+{
+  GtkWidget *widget;
+  GtkLabel *label;
+  widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
+  
+  if (widget == NULL)
+    /* State is defunct */
+    return NULL;
+  
+  /* Get label */
+  label = GTK_LABEL (widget);
+
+  return gail_text_util_get_text (GTK_LABEL_ACCESSIBLE (text)->textutil,
+                              gtk_label_get_layout (label), GAIL_AT_OFFSET, 
+                              boundary_type, offset, start_offset, end_offset);
+}
+
+static gchar*
+gtk_label_accessible_get_text_after_offset (AtkText         *text,
+                                 gint            offset,
+                                 AtkTextBoundary boundary_type,
+                                 gint            *start_offset,
+                                 gint            *end_offset)
+{
+  GtkWidget *widget;
+  GtkLabel *label;
+
+  widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
+  
+  if (widget == NULL)
+  {
+    /* State is defunct */
+    return NULL;
+  }
+  
+  /* Get label */
+  label = GTK_LABEL (widget);
+
+  return gail_text_util_get_text (GTK_LABEL_ACCESSIBLE (text)->textutil,
+                           gtk_label_get_layout (label), GAIL_AFTER_OFFSET, 
+                           boundary_type, offset, start_offset, end_offset);
+}
+
+static gint
+gtk_label_accessible_get_character_count (AtkText *text)
+{
+  GtkWidget *widget;
+  GtkLabel  *label;
+
+  widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
+  if (widget == NULL)
+    /* State is defunct */
+    return 0;
+
+  label = GTK_LABEL (widget);
+  return g_utf8_strlen (gtk_label_get_text (label), -1);
+}
+
+static gint
+gtk_label_accessible_get_caret_offset (AtkText *text)
+{
+   return GTK_LABEL_ACCESSIBLE (text)->cursor_position;
+}
+
+static gboolean
+gtk_label_accessible_set_caret_offset (AtkText *text, 
+                             gint    offset)
+{
+  GtkWidget *widget;
+  GtkLabel  *label;
+
+  widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
+  if (widget == NULL)
+    /* State is defunct */
+    return 0;
+
+  label = GTK_LABEL (widget);
+
+  if (gtk_label_get_selectable (label) &&
+      offset >= 0 &&
+      offset <= g_utf8_strlen (gtk_label_get_text (label), -1))
+    {
+      gtk_label_select_region (label, offset, offset);
+      return TRUE;
+    }
+  else
+    return FALSE;
+}
+
+static gint
+gtk_label_accessible_get_n_selections (AtkText *text)
+{
+  GtkWidget *widget;
+  GtkLabel  *label;
+  gint start, end;
+
+  widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
+  if (widget == NULL)
+    /* State is defunct */
+    return 0;
+
+  label = GTK_LABEL (widget);
+
+  if (!gtk_label_get_selectable (label))
+     return 0;
+
+  if (gtk_label_get_selection_bounds (label, &start, &end))
+     return 1;
+  else 
+     return 0;
+}
+
+static gchar*
+gtk_label_accessible_get_selection (AtkText *text,
+                         gint    selection_num,
+                          gint    *start_pos,
+                          gint    *end_pos)
+{
+  GtkWidget *widget;
+  GtkLabel  *label;
+
+  widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
+  if (widget == NULL)
+    /* State is defunct */
+    return NULL;
+
+  label = GTK_LABEL (widget);
+
+ /* Only let the user get the selection if one is set, and if the
+  * selection_num is 0.
+  */
+  if (!gtk_label_get_selectable( label) || selection_num != 0)
+     return NULL;
+
+  if (gtk_label_get_selection_bounds (label, start_pos, end_pos))
+    {
+      const gchar* label_text = gtk_label_get_text (label);
+    
+      if (label_text == NULL)
+        return 0;
+      else
+        return gail_text_util_get_substring (GTK_LABEL_ACCESSIBLE (text)->textutil, 
+                                             *start_pos, *end_pos);
+    }
+  else 
+    return NULL;
+}
+
+static gboolean
+gtk_label_accessible_add_selection (AtkText *text,
+                          gint    start_pos,
+                          gint    end_pos)
+{
+  GtkWidget *widget;
+  GtkLabel  *label;
+  gint start, end;
+
+  widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
+  if (widget == NULL)
+    /* State is defunct */
+    return FALSE;
+
+  label = GTK_LABEL (widget);
+
+  if (!gtk_label_get_selectable (label))
+     return FALSE;
+
+  if (! gtk_label_get_selection_bounds (label, &start, &end))
+    {
+      gtk_label_select_region (label, start_pos, end_pos);
+      return TRUE;
+    }
+  else
+    return FALSE;
+}
+
+static gboolean
+gtk_label_accessible_remove_selection (AtkText *text,
+                             gint    selection_num)
+{
+  GtkWidget *widget;
+  GtkLabel  *label;
+  gint start, end;
+
+  widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
+  if (widget == NULL)
+    /* State is defunct */
+    return FALSE;
+
+  if (selection_num != 0)
+     return FALSE;
+
+  label = GTK_LABEL (widget);
+
+  if (!gtk_label_get_selectable (label))
+     return FALSE;
+
+  if (gtk_label_get_selection_bounds (label, &start, &end))
+    {
+      gtk_label_select_region (label, 0, 0);
+      return TRUE;
+    }
+  else
+    return FALSE;
+}
+
+static gboolean
+gtk_label_accessible_set_selection (AtkText *text,
+                         gint    selection_num,
+                          gint    start_pos,
+                          gint    end_pos)
+{
+  GtkWidget *widget;
+  GtkLabel  *label;
+  gint start, end;
+
+  widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
+  if (widget == NULL)
+    /* State is defunct */
+    return FALSE;
+
+  if (selection_num != 0)
+     return FALSE;
+
+  label = GTK_LABEL (widget);
+
+  if (!gtk_label_get_selectable (label))
+     return FALSE;
+
+  if (gtk_label_get_selection_bounds (label, &start, &end))
+    {
+      gtk_label_select_region (label, start_pos, end_pos);
+      return TRUE;
+    }
+  else
+    return FALSE;
+}
+
+static void
+gtk_label_accessible_get_character_extents (AtkText      *text,
+                                 gint         offset,
+                                 gint         *x,
+                                 gint         *y,
+                                  gint                *width,
+                                  gint                *height,
+                                 AtkCoordType coords)
+{
+  GtkWidget *widget;
+  GtkLabel *label;
+  PangoRectangle char_rect;
+  const gchar *label_text;
+  gint index, x_layout, y_layout;
+  widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
+
+  if (widget == NULL)
+    /* State is defunct */
+    return;
+
+  label = GTK_LABEL (widget);
+  
+  gtk_label_get_layout_offsets (label, &x_layout, &y_layout);
+  label_text = gtk_label_get_text (label);
+  index = g_utf8_offset_to_pointer (label_text, offset) - label_text;
+  pango_layout_index_to_pos (gtk_label_get_layout (label), index, &char_rect);
+  
+  gail_misc_get_extents_from_pango_rectangle (widget, &char_rect, 
+                    x_layout, y_layout, x, y, width, height, coords);
+} 
+
+static gint 
+gtk_label_accessible_get_offset_at_point (AtkText      *text,
+                                gint         x,
+                                gint         y,
+                               AtkCoordType coords)
+{ 
+  GtkWidget *widget;
+  GtkLabel *label;
+  const gchar *label_text;
+  gint index, x_layout, y_layout;
+
+  widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
+  if (widget == NULL)
+    /* State is defunct */
+    return -1;
+  label = GTK_LABEL (widget);
+  
+  gtk_label_get_layout_offsets (label, &x_layout, &y_layout);
+  
+  index = gail_misc_get_index_at_point_in_layout (widget, 
+                                              gtk_label_get_layout (label), 
+                                              x_layout, y_layout, x, y, coords);
+  label_text = gtk_label_get_text (label);
+  if (index == -1)
+    {
+      if (coords == ATK_XY_WINDOW || coords == ATK_XY_SCREEN)
+        return g_utf8_strlen (label_text, -1);
+
+      return index;  
+    }
+  else
+    return g_utf8_pointer_to_offset (label_text, label_text + index);
+}
+
+static AtkAttributeSet*
+gtk_label_accessible_get_run_attributes (AtkText        *text,
+                               gint          offset,
+                               gint          *start_offset,
+                              gint           *end_offset)
+{
+  GtkWidget *widget;
+  GtkLabel *label;
+  AtkAttributeSet *at_set = NULL;
+  GtkJustification justify;
+  GtkTextDirection dir;
+
+  widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
+  if (widget == NULL)
+    /* State is defunct */
+    return NULL;
+
+  label = GTK_LABEL (widget);
+  
+  /* Get values set for entire label, if any */
+  justify = gtk_label_get_justify (label);
+  if (justify != GTK_JUSTIFY_CENTER)
+    {
+      at_set = gail_misc_add_attribute (at_set, 
+                                        ATK_TEXT_ATTR_JUSTIFICATION,
+     g_strdup (atk_text_attribute_get_value (ATK_TEXT_ATTR_JUSTIFICATION, justify)));
+    }
+  dir = gtk_widget_get_direction (widget);
+  if (dir == GTK_TEXT_DIR_RTL)
+    {
+      at_set = gail_misc_add_attribute (at_set, 
+                                        ATK_TEXT_ATTR_DIRECTION,
+     g_strdup (atk_text_attribute_get_value (ATK_TEXT_ATTR_DIRECTION, dir)));
+    }
+
+  at_set = gail_misc_layout_get_run_attributes (at_set,
+                                                gtk_label_get_layout (label),
+                                                gtk_label_get_text (label),
+                                                offset,
+                                                start_offset,
+                                                end_offset);
+  return at_set;
+}
+
+static AtkAttributeSet*
+gtk_label_accessible_get_default_attributes (AtkText        *text)
+{
+  GtkWidget *widget;
+  GtkLabel *label;
+  AtkAttributeSet *at_set = NULL;
+
+  widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
+  if (widget == NULL)
+    /* State is defunct */
+    return NULL;
+
+  label = GTK_LABEL (widget);
+  
+  at_set = gail_misc_get_default_attributes (at_set,
+                                             gtk_label_get_layout (label),
+                                             widget);
+  return at_set;
+}
+
+static gunichar 
+gtk_label_accessible_get_character_at_offset (AtkText           *text,
+                                    gint                offset)
+{
+  GtkWidget *widget;
+  GtkLabel *label;
+  const gchar *string;
+  gchar *index;
+
+  widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
+  if (widget == NULL)
+    /* State is defunct */
+    return '\0';
+
+  label = GTK_LABEL (widget);
+  string = gtk_label_get_text (label);
+  if (offset >= g_utf8_strlen (string, -1))
+    return '\0';
+  index = g_utf8_offset_to_pointer (string, offset);
+
+  return g_utf8_get_char (index);
+}
diff --git a/gtk/a11y/gtklabelaccessible.h b/gtk/a11y/gtklabelaccessible.h
new file mode 100644 (file)
index 0000000..58a60f0
--- /dev/null
@@ -0,0 +1,59 @@
+/* GAIL - The GNOME Accessibility Implementation Library
+ * Copyright 2001 Sun Microsystems Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GTK_LABEL_ACCESSIBLE_H__
+#define __GTK_LABEL_ACCESSIBLE_H__
+
+#include "gailwidget.h"
+#include "gailtextutil.h"
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_LABEL_ACCESSIBLE            (gtk_label_accessible_get_type ())
+#define GTK_LABEL_ACCESSIBLE(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_LABEL_ACCESSIBLE, GtkLabelAccessible))
+#define GTK_LABEL_ACCESSIBLE_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_LABEL_ACCESSIBLE, GtkLabelAccessibleClass))
+#define GTK_IS_LABEL_ACCESSIBLE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_LABEL_ACCESSIBLE))
+#define GTK_IS_LABEL_ACCESSIBLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_LABEL_ACCESSIBLE))
+#define GTK_LABEL_ACCESSIBLE_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_LABEL_ACCESSIBLE, GtkLabelAccessibleClass))
+
+typedef struct _GtkLabelAccessible      GtkLabelAccessible;
+typedef struct _GtkLabelAccessibleClass GtkLabelAccessibleClass;
+
+struct _GtkLabelAccessible
+{
+  GailWidget parent;
+
+  GailTextUtil   *textutil;
+  gint           cursor_position;
+  gint           selection_bound;
+  gint           label_length;
+  gulong         window_create_handler;
+  gboolean       has_top_level;
+};
+
+struct _GtkLabelAccessibleClass
+{
+  GailWidgetClass parent_class;
+};
+
+GType gtk_label_accessible_get_type (void);
+
+G_END_DECLS
+
+#endif /* __GTK_LABEL_ACCESSIBLE_H__ */
index 685429d9be7d666321c50d1fe74a7f12e4493600..8f213aa09f2f146fca98622b314c3af7b0c7a670 100644 (file)
@@ -52,6 +52,7 @@
 #include "gtkprivate.h"
 #include "gtktypebuiltins.h"
 
+#include "a11y/gtklabelaccessible.h"
 
 /**
  * SECTION:gtklabel
@@ -1093,6 +1094,8 @@ gtk_label_class_init (GtkLabelClass *class)
                                "activate-current-link", 0);
 
   g_type_class_add_private (class, sizeof (GtkLabelPrivate));
+
+  gtk_widget_class_set_accessible_type (widget_class, GTK_TYPE_LABEL_ACCESSIBLE);
 }
 
 static void